Čekání programu na skončení ShellExecuce
Otázka od: Lenka Donátová
23. 10. 2002 10:37
Pomocí ShellExecute spoustim pkzip.exe a potrebovala bych, aby se mi
nasledujici radky programu za timto prikazem zacaly provadet az po jeho
skonceni. Nechci pouzit Sleep protoze dopredu nevim jak dlouho bude operace
trvat. Zkousela jsem to pomoci vlaken, ale protoze jsem v tomto zacatecnik
tak se mi nepodarilo docilit toho co potrebuji. Poradte mi nekdo prosim jak
by to slo at uz pomoci vlaken nebo bez
Odpovedá: Tomáš Fajman
23. 10. 2002 12:21
Info.cbSize := SizeOf(SHELLEXECUTEINFO);
Info.Wnd := 0;
Info.lpVerb := Verb;
Info.lpFile := App;
Info.lpParameters := Params;
Info.lpDirectory := nil;
Info.fMask := SEE_MASK_NOCLOSEPROCESS;
Info.nShow := SW_SHOWNORMAL;
ShellExecuteEx(@Info);
if (Info.hProcess <> 0) then
WaitForSingleObject(Info.hProcess, INFINITE);
Odpovedá: Ludek ZITA
23. 10. 2002 10:56
----- Original Message -----
From: "Lenka Donátová" <lenkad@nemocnice-vs.cz>
> Pomocí ShellExecute spoustim pkzip.exe a potrebovala bych, aby se mi
> nasledujici radky programu za timto prikazem zacaly provadet az po jeho
> skonceni. Nechci pouzit Sleep protoze dopredu nevim jak dlouho bude
operace
> trvat. Zkousela jsem to pomoci vlaken, ale protoze jsem v tomto zacatecnik
> tak se mi nepodarilo docilit toho co potrebuji. Poradte mi nekdo prosim
jak
> by to slo at uz pomoci vlaken nebo bez
Ahoj.
Nejjednodussi je pouzit ShellExecAndWait z JCL (uses JCLSHell)
http://www.delphi-jedi.org/
Ludek
Odpovedá: Ludo Fulop
23. 10. 2002 12:01
----- Original Message -----
From: "Lenka Donátová" <lenkad@nemocnice-vs.cz>
> Pomocí ShellExecute spoustim pkzip.exe a potrebovala bych, aby se mi
> nasledujici radky programu za timto prikazem zacaly provadet az po jeho
> skonceni. Nechci pouzit Sleep protoze dopredu nevim jak dlouho bude
operace
Jan Sindelar - Tipy a Triky v Delphi, www.zive.cz:
Procedure ShellExecute_AndWait(FileName : String);
var
exInfo : TShellExecuteInfo;
Ph : DWORD;
begin
FillChar( exInfo, Sizeof(exInfo), 0 );
with exInfo do
begin
cbSize:= Sizeof( exInfo );
fMask := SEE_MASK_NOCLOSEPROCESS or SEE_MASK_FLAG_DDEWAIT;
Wnd := GetActiveWindow();
ExInfo.lpVerb := 'open';
lpFile:= PChar(FileName);
nShow := SW_SHOWNORMAL;
end;
if ShellExecuteEx(@exInfo) then
Ph := exInfo.HProcess;
else
begin
ShowMessage(SysErrorMessage(GetLastError));
exit;
end;
while WaitForSingleObject(ExInfo.hProcess, 50) <> WAIT_OBJECT_0 do
Application.ProcessMessages;
CloseHandle(Ph);
end;
Ludo Fulop
Odpovedá: Radek KALA
23. 10. 2002 12:50
Var
si : TStartUpInfo;
PI : TProcessInformation;
Begin
C := 'pkzip jmeno xxx';
P := ExtractFilePath(Application.ExeName);
SI.dwFlags := STARTF_USESHOWWINDOW;
SI.wShowWindow := SW_HIDE;
CreateProcess(nil,PCHAR(C),nil,nil,FALSE, CREATE_SEPARATE_WOW_VDM or
CREATE_DEFAULT_ERROR_MODE or CREATE_NEW_CONSOLE ,nil,PCHAR(P),SI,PI);
While WaitForSingleObject(PI.hProcess,1000) = WAIT_TIMEOUT Do Begin
Application.ProcessMessages;
End;
> Pomocí ShellExecute spoustim pkzip.exe a potrebovala bych, aby se mi
> nasledujici radky programu za timto prikazem zacaly provadet az po
> jeho skonceni. Nechci pouzit Sleep protoze dopredu nevim jak dlouho
> bude operace trvat. Zkousela jsem to pomoci vlaken, ale protoze jsem v
> tomto zacatecnik tak se mi nepodarilo docilit toho co potrebuji.
> Poradte mi nekdo prosim jak by to slo at uz pomoci vlaken nebo bez
>
S pozdravem Radek KALA
BetaControl, s.r.o.
Cerneho 58/60, 635 00
tlf. : + 420 5 4622 3491
fax : + 420 5 4622 3470
GSM : + 420 603 85 75 15
Odpovedá: Roman Macura
23. 10. 2002 12:26
Tohle funguje na Win95/98/ME/2000. Na WinXP jsem to nezkoušel.
{---------------------------------------------------------------------------
--
* This unit is based upon the well-known *
* and largely used WinExecAndWait function*
* The former WinexecAndWait function *
*
doesn't compile under Delphi 2.0 *
* because the GetModuleUsage function is *
* no longer supported under Win95. *
* I have simply updated the previous code *
* so that it works with Delphi 2.0 under *
* Windows 95. With this function you can *
* call Windows-based applications as well *
* as Dos-based commands. *
* That is 'c:\myapp\app32.exe' as well as *
* 'command.com
/c del
*.bak'. * *
* USAGE: *
* *
* err:=WinExecAndWait32( *
* Full FileName & *
* command-line parameters, *
* SW_HIDE/SW_SHOW, *
* 0 or output file handle); *
* if err<>0 then *
* showmessage('Error!'); *
* *
----------------------------------------------------------------------------
-}
unit WinExc32;
interface
uses windows, messages;
function WinExecAndWait32(Path: PChar; Visibility:
Word;OutTo:integer;Directory:PChar=nil): integer;
function WinExec32(Path: PChar; Visibility: Word;OutTo:integer): integer;
function WinExecAndWait32WithExitCode(Path: PChar; Visibility:
Word;OutTo:integer;var ExitCode:Cardinal;Directory:PChar=nil): integer;
implementation
function WinExecAndWait32(Path: PChar; Visibility:
Word;OutTo:Integer;Directory:PChar=nil): integer;
var
Msg: TMsg;
lpExitCode : Cardinal;
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
InhHndls:Boolean;
begin
FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
with StartupInfo do
begin
InhHndls:=False;
cb := SizeOf(TStartupInfo);
dwFlags := STARTF_USESHOWWINDOW or STARTF_FORCEONFEEDBACK;
if OutTo<>0 then
begin
dwFlags:=dwFlags or STARTF_USESTDHANDLES;
InhHndls:=True;
hStdInput:=0;
hStdError:=0;
hStdOutput:=OutTo;
end;
wShowWindow := visibility; {you could pass sw_show or sw_hide as
parameter}
end;
if CreateProcess(nil, path, nil, nil, InhHndls,
NORMAL_PRIORITY_CLASS, nil, Directory, StartupInfo, ProcessInfo) then
begin
repeat
while PeekMessage(Msg, 0, 0, 0, pm_Remove) do
begin
if Msg.Message = wm_Quit then Halt(Msg.WParam);
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
GetExitCodeProcess(ProcessInfo.hProcess,lpExitCode);
until lpExitCode<>Still_Active;
with ProcessInfo do {not sure this is necessary but seen in in some code
elsewhere}
begin
CloseHandle(hThread);
CloseHandle(hProcess);
end;
result := 0; {sucess}
end
else
result:=GetLastError;{error occurs during CreateProcess see help for
details}
end;
function WinExec32(Path: PChar; Visibility: Word;OutTo:integer): integer;
var
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
InhHndls:boolean;
begin
FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
with StartupInfo do
begin
InhHndls:=false;
cb := SizeOf(TStartupInfo);
dwFlags := STARTF_USESHOWWINDOW or STARTF_FORCEONFEEDBACK;
if OutTo<>0 then
begin
dwFlags:=dwFlags or STARTF_USESTDHANDLES;
InhHndls:=true;
hStdOutput:=OutTo;
end;
wShowWindow := visibility; {you could pass sw_show or sw_hide as
parameter}
end;
if CreateProcess(nil,path,nil, nil, InhHndls,
NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo) then
result := 0 {sucess}
else
result:=GetLastError;{error occurs during CreateProcess see help for
details}
end;
function WinExecAndWait32WithExitCode(Path: PChar; Visibility:
Word;OutTo:integer;var ExitCode:Cardinal;Directory:PChar=nil): integer;
var
Msg: TMsg;
outto2,lpExitCode : cardinal;
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
InhHndls:boolean;
SA:Security_Attributes;
VerInfo: TOSVersionInfo;
cont:Boolean;
begin
outto2:=0;
ExitCode:=0;
FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
with StartupInfo do
begin
InhHndls:=false;
cb := SizeOf(TStartupInfo);
dwFlags := STARTF_USESHOWWINDOW or STARTF_FORCEONFEEDBACK;
if OutTo<>0 then
begin
dwFlags:=dwFlags or STARTF_USESTDHANDLES;
InhHndls:=true;
hStdInput:=0;
hStdError:=0;
hStdOutput:=OutTo;
end;
wShowWindow := visibility; {you could pass sw_show or sw_hide as
parameter}
end;
VerInfo.dwOSVersionInfoSize:=sizeof(TOSVERSIONINFO);
GetVersionEx(VerInfo);
if VerInfo.dwPlatformId in [VER_PLATFORM_WIN32_NT] then
begin
SA.nLength:=SizeOf(PSECURITYATTRIBUTES);
SA.bInheritHandle:=inhhndls;
SA.lpSecurityDescriptor:=nil;
if inhhndls then
begin
DuplicateHandle(GetCurrentProcess,outto,GetCurrentProcess,@outto2,0,True,DUP
LICATE_SAME_ACCESS);
Startupinfo.hStdOutput:=outto2;
end;
cont:=CreateProcess(nil, path, @sa, nil, InhHndls,
NORMAL_PRIORITY_CLASS, nil, Directory, StartupInfo, ProcessInfo);
end
else
cont:=CreateProcess(nil, path, nil, nil, InhHndls,
NORMAL_PRIORITY_CLASS, nil, Directory, StartupInfo, ProcessInfo);
if cont then
begin
repeat
while PeekMessage(Msg, 0, 0, 0, pm_Remove) do
begin
if Msg.Message = wm_Quit then Halt(Msg.WParam);
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
GetExitCodeProcess(ProcessInfo.hProcess,lpExitCode);
until lpExitCode<>Still_Active;
ExitCode:=lpExitCode;
with ProcessInfo do {not sure this is necessary but seen in in some code
elsewhere}
begin
if outto2<>0 then
CloseHandle(outto2);
CloseHandle(hThread);
CloseHandle(hProcess);
end;
result := 0; {sucess}
end
else
result:=GetLastError;{error occurs during CreateProcess see help for
details}
end;
end.
Roman.
----- Original Message -----
From: "Lenka Donátová" <lenkad@nemocnice-vs.cz>
To: <delphi-l@clexpert.cz>
Sent: Wednesday, October 23, 2002 11:38 AM
Subject: Čekání programu na skončení ShellExecuce
> Pomocí ShellExecute spoustim pkzip.exe a potrebovala bych, aby se mi
> nasledujici radky programu za timto prikazem zacaly provadet az po jeho
> skonceni. Nechci pouzit Sleep protoze dopredu nevim jak dlouho bude
operace
> trvat. Zkousela jsem to pomoci vlaken, ale protoze jsem v tomto zacatecnik
> tak se mi nepodarilo docilit toho co potrebuji. Poradte mi nekdo prosim
jak
> by to slo at uz pomoci vlaken nebo bez
>
>
Odpovedá: Vymazal Milan
23. 10. 2002 15:36
Ja pouzivam tohle
function WinExecAndWait32(FileName:String; Visibility : integer):integer;
var
zAppName:array[0..512] of char;
zCurDir:array[0..255] of char;
WorkDir:String;
StartupInfo:TStartupInfo;
ProcessInfo:TProcessInformation;
begin
StrPCopy(zAppName,FileName);
GetDir(0,WorkDir);
StrPCopy(zCurDir,WorkDir);
FillChar(StartupInfo,Sizeof(StartupInfo),#0);
StartupInfo.cb := Sizeof(StartupInfo);
StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow := Visibility;
if not CreateProcess(nil,
zAppName, { pointer to command line string }
nil, { pointer to process security attributes }
nil, { pointer to thread security attributes }
false, { handle inheritance flag }
CREATE_NEW_CONSOLE or { creation flags }
NORMAL_PRIORITY_CLASS,
nil, { pointer to new environment block }
nil, { pointer to current directory name }
StartupInfo, { pointer to STARTUPINFO }
ProcessInfo) then Result := -1 { pointer to PROCESS_INF }
else begin
WaitforSingleObject(ProcessInfo.hProcess,INFINITE);
GetExitCodeProcess(ProcessInfo.hProcess,Result);
end;
end;